package com.dabao.service.impl;

import com.dabao.bean.Phone;
import com.dabao.dao.PhoneDao;
import com.dabao.query.PhoneQuery;
import com.dabao.service.SearchService;
import com.dabao.util.KeyConstant;
import com.google.common.base.CharMatcher;
import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.net.ssl.*;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;

/**
 * Created by card on 2016/5/30.
 */
@Service
public class SearchService360 implements SearchService, Runnable {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private PhoneDao phoneDao;

    @Autowired
    private RedisService redisService;

    static {
        try {
            trustAllHttpsCertificates();
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
                public boolean verify(String s, SSLSession sslSession) {
                    return true;
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @PostConstruct
    public void init() {
        new Thread(this).start();
    }

    public void search(String key, String phoneNumber) {
        try {
            String remark = "";
            String number = CharMatcher.digit().retainFrom(phoneNumber);
            Document document = Jsoup.connect("https://www.so.com/s?q=" + number).get();
            Elements elements = document.getElementsByClass("mohe-ph-mark");
            if (elements.size() > 0) {
                Element element = elements.get(0);
                remark = "360" + element.text();
                logger.info("{} {}", number, remark);
            }

            PhoneQuery query = new PhoneQuery();
            query.setPhone(number);
            List<Phone> phones = phoneDao.selectList(query);
            if(phones.size() > 0 && StringUtils.isNotBlank(remark)) {
                Phone phone = phones.get(0);
                phone.setRemark(remark);
                phone.setType(1);
                phoneDao.update(phone);
            }

            else if(phones.size() == 0){
                Phone phone = new Phone();
                phone.setPhone(number);
                phone.setRemark(remark);
                if(StringUtils.isBlank(remark)) {
                    phone.setType(0);
                }
                else {
                    phone.setType(1);
                }
                phoneDao.insert(phone);
            }

        } catch (Exception e) {
            logger.error("Exception", e);
        }
    }

    public void insert(Phone phone) {
        PhoneQuery query = new PhoneQuery();
        query.setPhone(phone.getPhone());
        List<Phone> phones = phoneDao.selectList(query);
        if(phones.size() > 0) {
            phone.setId(phones.get(0).getId());
            phoneDao.update(phone);
        }

        else {
            phoneDao.insert(phone);
        }
    }

    private static void trustAllHttpsCertificates() throws Exception {
        TrustManager[] trustAllCerts = new TrustManager[1];
        TrustManager tm = new miTM();
        trustAllCerts[0] = tm;
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }

    public void run() {
        while (true) {
            try {
                Map<String, String> map = redisService.hgetAll(KeyConstant.KEY_MAP);
                for(String key : map.keySet()) {
                    String phone = redisService.lpop(key);
                    if(StringUtils.isNotBlank(phone)) {
                        search(key, phone);
                    }

                    Long len = redisService.llen(key);
                    if(len == null || len == 0) {
                        redisService.hdel(KeyConstant.KEY_MAP, key);
                    }
                }
                Thread.sleep(500);
            } catch (Exception e) {
                logger.error("error", e);
            }
        }
    }

    static class miTM implements TrustManager, X509TrustManager {

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public boolean isServerTrusted(X509Certificate[] certs) {
            return true;
        }

        public boolean isClientTrusted(X509Certificate[] certs) {
            return true;
        }

        public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
            return;
        }

        public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
            return;
        }
    }
}
